#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include "logger.h"
#include "headset.h"

// 支持多个耳机设备定义
typedef struct {
    unsigned short vid;
    unsigned short pid;
    char* name;
    int protocol_type; // 协议类型：0=标准，1=华为，2=苹果，等等
} HeadsetDevice;

// 已知支持的耳机设备列表
static const HeadsetDevice known_devices[] = {
    {0x12D1, 0x3A07, "Huawei Headset", 1},   // 华为耳机
    {0x05AC, 0x12A8, "Apple Headset", 2},    // 苹果耳机示例
    {0x046D, 0x0A38, "Logitech Headset", 0}, // 罗技耳机示例
    {0x1532, 0x0504, "Razer Headset", 0},    // 雷蛇耳机示例
    {0x045E, 0x070F, "Microsoft Headset", 0} // 微软耳机示例
    // 可以继续添加更多设备
};

#define NUM_KNOWN_DEVICES (sizeof(known_devices) / sizeof(HeadsetDevice))
// 当前设备的协议类型
static int current_protocol_type = 0;

// 新增超时和双击检测常量
#define WAIT_TIMEOUT_MS      200  // 等待超时时间(毫秒)
#define DOUBLECLICK_TIME_MS  200  // 双击时间阈值(毫秒)
// 添加按键重复触发相关常量
#define KEY_REPEAT_DELAY_MS  500  // 首次重复延迟(毫秒)
#define KEY_REPEAT_RATE_MS   100  // 重复速率(毫秒)
// 添加长按检测相关常量
#define LONG_PRESS_TIME_MS   1000 // 长按触发时间(毫秒)

// 辅助函数：获取毫秒级时间戳
static unsigned long get_time_ms() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}

// 检查设备是否为已知设备
static int check_device_info(int fd, unsigned short *vid, unsigned short *pid) {
    // Linux中获取设备信息
    unsigned short id[4];
    memset(id, 0, sizeof(id));
    
    if (ioctl(fd, EVIOCGID, id) < 0) {
        return 0;
    }
    
    *vid = id[ID_VENDOR];
    *pid = id[ID_PRODUCT];
    
    return 1;
}

// 查找并打开headset设备
static int open_headset_input_device() {
    int fd = -1;
    DIR *dir;
    struct dirent *entry;
    char device_path[64];
    unsigned short vid, pid;
    
    // 遍历/dev/input目录下的事件设备
    if ((dir = opendir("/dev/input")) == NULL) {
        ilog("Headset: Cannot open /dev/input directory\n");
        return -1;
    }
    
    while ((entry = readdir(dir)) != NULL) {
        // 只处理eventX设备
        if (strncmp(entry->d_name, "event", 5) != 0) {
            continue;
        }
        
        snprintf(device_path, sizeof(device_path), "/dev/input/%s", entry->d_name);
        fd = open(device_path, O_RDONLY | O_NONBLOCK);
        if (fd < 0) {
            continue;
        }
        
        // 检查设备信息
        if (check_device_info(fd, &vid, &pid)) {
            dlog("Headset: HID device VID=0x%04X, PID=0x%04X\n", vid, pid);
            
            // 检查是否为已知设备
            for (int i = 0; i < NUM_KNOWN_DEVICES; i++) {
                if (vid == known_devices[i].vid && pid == known_devices[i].pid) {
                    ilog("  supported headset device: %s\n", known_devices[i].name);
                    current_protocol_type = known_devices[i].protocol_type;
                    closedir(dir);
                    return fd;
                }
            }
            
            // 检查是否为通用音频设备
            char name[256] = {0};
            if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) {
                dlog("  device name: %s\n", name);
                
                // 转换为小写以便比较
                char lower_name[256] = {0};
                strncpy(lower_name, name, sizeof(lower_name) - 1);
                lower_name[sizeof(lower_name) - 1] = '\0'; // 确保字符串以null结尾
                for (char *p = lower_name; *p; ++p) {
                    *p = tolower(*p);
                }      
                // 检查是否包含耳机相关关键词
                if (strstr(lower_name, "headset") || 
                    strstr(lower_name, "earphone") ||
                    strstr(lower_name, "headphone") ||
                    strstr(lower_name, "audio")) {
                    ilog("%s: generic audio device\n", name);
                    current_protocol_type = 0; // 使用标准协议
                    closedir(dir);
                    return fd;
                }
            }
            dlog("  not a supported headset device\n");
        }
        
        close(fd);
    }
    
    closedir(dir);
    return -1;
}

// 解析Linux输入事件为耳机按键
static HeadsetButton parse_linux_event(struct input_event *ev) {
    // 只处理按键事件
    if (ev->type != EV_KEY) {
        return BUTTON_NONE;
    }
    
    // 检查按键值并映射到耳机按钮
    switch (ev->code) {
        case KEY_VOLUMEUP:
            return (ev->value) ? BUTTON_VOLINC : BUTTON_NONE;
            
        case KEY_VOLUMEDOWN:
            return (ev->value) ? BUTTON_VOLDDEC : BUTTON_NONE;
            
        case KEY_PLAYPAUSE:
        case KEY_PLAY:
        case KEY_PAUSE:
            return (ev->value) ? BUTTON_PLAYPAUSE : BUTTON_NONE;
            
        case KEY_NEXTSONG:
            return (ev->value) ? BUTTON_NEXT : BUTTON_NONE;
            
        case KEY_PREVIOUSSONG:
            return (ev->value) ? BUTTON_PREV : BUTTON_NONE;
            
        // 有些设备可能使用其他按键
        case KEY_MEDIA:
        case KEY_MUTE:
            // 根据不同协议类型进行特殊处理
            if (current_protocol_type == 1) { // 华为协议
                return (ev->value) ? BUTTON_PLAYPAUSE : BUTTON_NONE;
            }
            break;
    }
    
    return BUTTON_NONE;
}


// 获取耳机按键事件
#define LOG_DEVICE_NOT_FOUND_RATE_MS 300000 // 设备未找到时的重试间隔 5*60s = 300000ms
HeadsetButton get_headset_button() {
    
    int fd = open_headset_input_device();
    if (fd < 0) {
        static unsigned long lastLogTime = 0; // 上次日志记录时间
        unsigned long currentTime = get_time_ms();
        // 如果设备未找到，且距离上次日志记录超过指定时间 ，则记录日志
        if (currentTime - lastLogTime > LOG_DEVICE_NOT_FOUND_RATE_MS) {
            lastLogTime = currentTime; // 更新上次日志记录时间
            ilog("Headset: device not found\n");
        }
        usleep(WAIT_TIMEOUT_MS * 1000); // 如果没有找到设备，等待一段时间后重试
        return BUTTON_NONE;
    }
    
    // 添加双击检测变量
    static unsigned long lastPlayPauseTime = 0;
    static int playPauseClickCount = 0;
    // 添加音量按键状态跟踪变量
    static int isVolIncPressed = 0;
    static int isVolDecPressed = 0;
    static unsigned long lastVolIncPressTime = 0;
    static unsigned long lastVolDecPressTime = 0;
    // 添加长按检测变量
    static int isLongPressDetected = 0;
    static unsigned long pressStartTime = 0;
    
    unsigned long currentTime;
    HeadsetButton buttonPressed = BUTTON_NONE;
    
    struct input_event ev;
    fd_set rfds;
    struct timeval tv;
    int waitTimeoutMs = -1;  // -1表示无限等待
    
    while (1) {
        FD_ZERO(&rfds);
        FD_SET(fd, &rfds);
        
        // 设置超时
        if (isVolIncPressed || isVolDecPressed) {
            waitTimeoutMs = KEY_REPEAT_RATE_MS;
        } else if (playPauseClickCount > 0) {
            waitTimeoutMs = WAIT_TIMEOUT_MS;
        } else if (pressStartTime > 0) {
            waitTimeoutMs = LONG_PRESS_TIME_MS - (get_time_ms() - pressStartTime);
            if (waitTimeoutMs < 0) waitTimeoutMs = 0;
        } else {
            waitTimeoutMs = -1; // 无限等待
        }
        
        // 转换为timeval结构
        if (waitTimeoutMs >= 0) {
            tv.tv_sec = waitTimeoutMs / 1000;
            tv.tv_usec = (waitTimeoutMs % 1000) * 1000;
        }
        
        // 等待事件或超时
        int ret = select(fd + 1, &rfds, NULL, NULL, 
                         (waitTimeoutMs >= 0) ? &tv : NULL);
        
        // 获取当前时间
        currentTime = get_time_ms();
        
        if (ret == 0) {
            // 超时处理
            // 检查是否需要触发音量键重复事件
            if (isVolIncPressed && 
                (currentTime - lastVolIncPressTime) > KEY_REPEAT_DELAY_MS) {
                buttonPressed = BUTTON_VOLINC;
                break;
            }
            
            if (isVolDecPressed && 
                (currentTime - lastVolDecPressTime) > KEY_REPEAT_DELAY_MS) {
                buttonPressed = BUTTON_VOLDDEC;
                break;
            }
            
            // 检查播放暂停双击
            if (playPauseClickCount == 1 && (currentTime - lastPlayPauseTime) > DOUBLECLICK_TIME_MS) {
                // 如果超过双击时间，认为是单击
                playPauseClickCount = 0;
                buttonPressed = BUTTON_PLAYPAUSE;
                break;
            }
            
            // 检查长按
            if (pressStartTime > 0 && !isLongPressDetected && 
                (currentTime - pressStartTime) > LONG_PRESS_TIME_MS) {
                isLongPressDetected = 1;
                buttonPressed = BUTTON_PREV; // 长按通常映射为上一曲
                break;
            }
            
            if (buttonPressed != BUTTON_NONE)
                break;
            else
                continue;
        } else if (ret < 0) {
            // 错误处理
            if (errno != EINTR) {
                ilog("Headset:  Select error %s\n", strerror(errno));
                break;
            }
            continue;
        }
        
        // 读取事件
        ssize_t n = read(fd, &ev, sizeof(ev));
        if (n != sizeof(ev)) {
            if (errno != EAGAIN) {
                ilog("Headset: Read event error %s\n", strerror(errno));
                break;
            }
            continue;
        }
        
        // 解析事件
        HeadsetButton button = parse_linux_event(&ev);
        
        // 处理解析出的按键
        switch (button) {
            case BUTTON_VOLINC:
                if (!isVolIncPressed) {
                    isVolIncPressed = 1;
                    lastVolIncPressTime = currentTime;
                }
                buttonPressed = BUTTON_VOLINC;
                break;
                
            case BUTTON_VOLDDEC:
                if (!isVolDecPressed) {
                    isVolDecPressed = 1;
                    lastVolDecPressTime = currentTime;
                }
                buttonPressed = BUTTON_VOLDDEC;
                break;
                
            case BUTTON_PLAYPAUSE:
                // 记录按下开始时间(用于长按检测)
                if (pressStartTime == 0) {
                    pressStartTime = currentTime;
                }
                
                // 检测是否为双击
                if (playPauseClickCount > 0 && (currentTime - lastPlayPauseTime) < DOUBLECLICK_TIME_MS) {
                    // 是双击，重置计数器并返回NEXT
                    playPauseClickCount = 0;
                    pressStartTime = 0;
                    buttonPressed = BUTTON_NEXT;
                    break;
                } else {
                    // 记录第一次点击
                    playPauseClickCount = 1;
                    lastPlayPauseTime = currentTime;
                }
                continue; // 继续等待可能的第二次点击
                
            case BUTTON_NONE:
                // 按键释放处理
                isVolIncPressed = 0;
                isVolDecPressed = 0;
                
                // 如果有按键释放，重置长按状态
                if (pressStartTime > 0 && !isLongPressDetected) {
                    // 非长按释放
                    pressStartTime = 0;
                }
                isLongPressDetected = 0;
                pressStartTime = 0;
                continue;
                
            default:
                // 其他按键直接返回
                buttonPressed = button;
                break;
        }
        
        if (buttonPressed != BUTTON_NONE) {
            break;  // 跳出循环
        }
    }
    
    // 清理资源
    close(fd);
    if(buttonPressed != BUTTON_NONE) {
        ilog("Headset: button %d pressed\n", buttonPressed);
    }
    return buttonPressed;
}

#ifdef TEST
int main() {
    while(1) {
        HeadsetButton button = get_headset_button();
        switch (button) {
            case BUTTON_VOLINC:
                printf("Volume Increase Button Pressed\n");
                break;
            case BUTTON_VOLDDEC:
                printf("Volume Decrease Button Pressed\n");
                break;
            case BUTTON_PLAYPAUSE:
                printf("Play/Pause Button Pressed\n");
                break;
            case BUTTON_NEXT:
                printf("Next Track Button Pressed\n");
                break;
            case BUTTON_PREV:
                printf("Previous Track Button Pressed\n");
                break;
            default:
                printf("No Button Pressed\n");
        }
    }
    return 0;
}
#endif // TEST